package com.hxhy.service;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.hxhy.bean.Account;
import com.hxhy.bean.BElectronic;
import com.hxhy.bean.Electronic;
import com.hxhy.bean.ElectronicException;
import com.hxhy.bean.Taxrate;
import com.hxhy.util.AesUtilTest;
import com.hxhy.util.RSADemo;
import com.hxhy.util.Tools;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import nuonuo.open.sdk.NNOpenSDK;

/**
 * 抚松税控接口(诺诺网:https://open.jss.com.cn/#/api-doc/common-api?id=100209)
 * 【抚松县新城热力有限公司】名称：抚松县新城热力有限公司 纳税人识别号：912206213400630408 Aisino123
 * 地址、电话：抚松县松江河镇长白山国际旅游度假区北区东经街80号 0439-6973555
 * 开户行及账号：吉林银行股份有限公司白山抚松支行0912011000002072
 */
@Service("fsxcrl")
public class InvoiceServiceImpl3 extends InvoiceServiceImpl implements InvoiceService {

	@Autowired
	Electronic ele;

	// 私有属性
	private static String appKey = "42511660";
	private static String appSecret = "3CB3B2D429984AE2";
	private static String token = "32f3a6077d7970eb38a2960gioehrxls";
	private static String kp = "nuonuo.ElectronInvoice.requestBillingNew";// 开票
	private static String hc = "nuonuo.electronInvoice.invoiceCancellation";// 作废
	private static String cx = "nuonuo.ElectronInvoice.queryInvoiceResult";// 查询
	// private String lj = "nuonuo.ElectronInvoice.GetClientStatus";// 在线检测
	private String ck = "nuonuo.ElectronInvoice.deliveryInvoice";// 重新交付

	// 状态表示
	private static final String SUCCESS = "E0000";
	// 终端分布 名称,分机号, 终端号
	private static String[][] users;

	@Override
	public void init() {
		super.init();
		// 单独的收费员分机号配置
		String sql = "SELECT value mc,valuecode zdh,usedcounts fjh FROM s_enum WHERE typecode='invoice_user' ";
		List<Map<String, Object>> list = mapper.execSelectListMap(sql);
		if (list == null || list.size() == 0) {
			log.info("未读取到收费员信息,请检查枚举设置..");
		}

		users = new String[list.size()][];
		for (int i = 0; i < users.length; i++) {
			Map<String, Object> map = list.get(i);
			users[i] = new String[] { map.get("mc").toString(), map.get("fjh").toString(), map.get("zdh").toString() };
		}
	}

	private static int first(BElectronic fp) {
		int tmp = -1;
		if ("增值税普通发票".equals(fp.getInvoicemethod())) {
			for (int i = 0; i < users.length; i++) {
				if (users[i][0].equals(fp.getCreater())) {
					tmp = i;
					break;
				}
			}
			if (-1 == tmp)
				tmp = 0;
			fp.setKpr(users[tmp][0]);
			if (tmp < users.length - 2) {
				fp.setSkr(users[tmp + 1][0]);
				fp.setFhr(users[tmp + 2][0]);
			} else {
				fp.setSkr(users[0][0]);
				if (1 < users.length) {
					fp.setFhr(users[1][0]);
				} else {
					fp.setFhr(users[0][0]);
				}
			}
		} else {
			fp.setReturncode("9999");
			fp.setReturnstate("开增值税发票请选择发票类型为增值税普通发票");
		}
		return tmp;
	}

	/**
	 * @税控
	 */
	@Override
	public BElectronic kpInvoice(BElectronic fp) throws ElectronicException {
		if (token == null) {
			return error(fp, "未获取到token,请重启发票服务....");
		}
		log.info("当前token: " + token);
		if (users == null || users.length == 0) {
			return error(fp, "未读取到收费员信息,请检查枚举设置并重启发票服务....");
		}

		int n = first(fp);
		if (-1 == n) {
			return fp;
		}
		BigDecimal paysum = BigDecimal.ZERO;
		JSONObject order = new JSONObject();
		if (Tools.isNullOrEmpty(fp.getGfmc()))
			return error(fp, "购方名称不能为空");
		if (Tools.isNullOrEmpty(fp.getActs()))
			return error(fp, "无账目信息");
		order.put("buyerName", Tools.toString(fp.getGfmc()));
		order.put("buyerTaxNum", Tools.toString(fp.getNsrsbh()));
		order.put("buyerTel", Tools.toString(fp.getTel()));
		order.put("buyerAddress", Tools.toString(fp.getDz()));
		order.put("buyerAccount", Tools.toString(fp.getKhh()));
		order.put("salerTaxNum", Tools.toString(ele.nsrsbh));
		order.put("salerTel", Tools.toString(ele.nsrdh));
		order.put("salerAddress", Tools.toString(ele.nsrdz));
		order.put("salerAccount", Tools.toString(ele.yhzh));
		order.put("orderNo", Tools.getUUID());
		order.put("invoiceDate", Tools.toString(Tools.DATEFORMAT_Y_M_D_HMS.format(new Date())));
		order.put("remark", Tools.toString(fp.getRemark()));
		order.put("checker", Tools.toString(fp.getFhr()));
		order.put("payee", Tools.toString(fp.getSkr()));
		order.put("clerk", Tools.toString(fp.getKpr()));
		order.put("pushMode", Tools.toString(!Tools.isNullOrEmpty(fp.getTel()) && !Tools.isNullOrEmpty(fp.getEmail())
				? "2" : !Tools.isNullOrEmpty(fp.getTel()) ? "1" : !Tools.isNullOrEmpty(fp.getEmail()) ? "0" : "-1"));
		order.put("buyerPhone", Tools.toString(fp.getTel()));
		order.put("email", Tools.toString(fp.getEmail()));
		order.put("invoiceType", "1");
		order.put("invoiceLine", "c");
		order.put("extensionNumber", users[n][1]);
		order.put("terminalNumber", users[n][2]);
		JSONArray array = new JSONArray();
		for (Account mp : fp.getActs()) {
			if (!"1".equals(mp.getActflag1()) && !"5".equals(mp.getActflag1())) {
				continue;
			}
			JSONObject dtl = new JSONObject();
			Taxrate taxrate = tax.get(mp.getAreakind());
			if (0 == BigDecimal.ZERO.compareTo(mp.getArea())) {
				mp.setArea(BigDecimal.ONE);
			}
			if ("1".equals(mp.getActflag1())) {
				mp.setAreaname(Tools.toString(taxrate.getAreaname()));
			} else if ("5".equals(mp.getActflag1())) {
				mp.setAreaname(Tools.toString(taxrate.getAreaname()).concat("-违约金"));
			}
			dtl.put("goodsName", mp.getAreaname());
			dtl.put("goodsCode", "11001020101");
			dtl.put("withTaxFlag", taxrate.getIsdutyfree());
			dtl.put("specType", Tools.toString(mp.getAnnual()));
			dtl.put("unit", "平方米");
			if ("1".equals(taxrate.getIsdutyfree())) {
				mp.setReceivedsum(
						mp.getReceived().divide(BigDecimal.ONE.add(taxrate.getTaxrate()), 8, BigDecimal.ROUND_HALF_UP));
				mp.setSe(mp.getReceived().subtract(mp.getReceivedsum()));
			} else {
				mp.setReceivedsum(mp.getReceived());
				mp.setSe(BigDecimal.ZERO);
			}
			dtl.put("tax", Tools.toString(mp.getSe()));
			dtl.put("taxRate", isdutyfree(mp) ? "0" : Tools.toString(taxrate.getTaxrate()));
			dtl.put("num", Tools.toString(mp.getArea()));
			dtl.put("price", Tools.toString(mp.getReceived().divide(mp.getArea(), 8, BigDecimal.ROUND_HALF_UP)));
			dtl.put("taxExcludedAmount", Tools.toString(mp.getReceivedsum()));
			dtl.put("taxIncludedAmount", Tools.toString(mp.getReceived()));
			dtl.put("favouredPolicyName", isdutyfree(mp) ? "免税" : "");
			dtl.put("favouredPolicyFlag", isdutyfree(mp) ? "1" : "");
			dtl.put("zeroRateFlag", isdutyfree(mp) ? "1" : "");
			array.add(dtl);
			paysum = paysum.add(mp.getReceived());
		}
		order.put("invoiceDetail", Tools.toString(array));
		JSONObject content = new JSONObject();
		content.put("order", order);
		if (1 == paysum.compareTo(new BigDecimal(ele.max))) {
			fp.setReturncode("9999");
			fp.setReturnstate("开票金额超上限");
		}
		log.info("开票请求报文:" + content.toString());
		JSONObject web = web(ele.url, kp, content.toString());
		log.info(web.toString());
		if (web != null && SUCCESS.equals(web.getString("code"))) {
			fp.setReturncode("0000");
			fp.setLsh(web.getJSONObject("result").getString("invoiceSerialNum"));
			fp.setFlag("0");
			fp.setInvoicekind("正票");
			fp.setMoney(paysum);
		} else {
			fp.setReturncode("9999");
			fp.setReturnstate(web.getString("describe"));
		}

		if (!"0000".equals(fp.getReturncode()))
			return fp;

		// 查询开票结果
		StringBuilder search = new StringBuilder();
		search.append("{\"isOfferInvoiceDetail\": \"\", \"orderNos\": [], \"serialNos\": [");
		search.append("\"").append(fp.getLsh()).append("\"");
		search.append("]}");
		// 循环查找直至有结果
		for (int num = 0; num < 5; num++) {
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			web = web(ele.url, cx, search.toString());
			log.info("查询结果:" + web.toString());
			if (web != null && SUCCESS.equals(web.getString("code"))) {
				array = web.getJSONArray("result");
				web = JSONObject.fromObject(array.get(0));
				if ("20".equals(web.getString("status")) || "21".equals(web.getString("status"))) {
					continue;
				}
				if ("2".equals(web.getString("status"))) {
					fp.setReturncode("0000");
					fp.setReturnstate(web.getString("statusMsg"));
					fp.setPdfpath(web.getString("pdfUrl"));
					fp.setInvoicenum(web.getString("invoiceNo"));
					fp.setInvoiceversion(web.getString("invoiceCode"));
				} else {
					fp.setReturncode("9999");
					fp.setReturnstate(web.getString("failCause"));
				}
				break;
			}
		}
		// 客户端在线状态检测
		/*
		 * StringBuilder test = new StringBuilder();
		 * test.append("{\"sellerTaxNo\": \"").append(ele.nsrsbh).
		 * append("\",\"extensionNumber\": \"0\"}"); web = web(ele.url, lj,
		 * test.toString()); if (web != null &&
		 * SUCCESS.equals(web.getString("code"))) { if
		 * (!"1".equals(web.getJSONObject("result").getString("onlineStatus")))
		 * { fp.setReturncode("9999"); fp.setReturnstate("打印机不在线"); } }
		 */

		if (!"0000".equals(fp.getReturncode()))
			return fp;

		// 密文
		if ("0000".equals(fp.getReturncode())) {
			try {
				fp.setPdfbytes(jiami(fp.getInvoicenum(), fp.getInvoiceversion(), paysum));
			} catch (Exception e) {
				log.info(Tools.getErrorException(e));
			}
		}

		return fp;
	}

	/**
	 * @税控
	 */
	@Override
	@Transactional
	public BElectronic hpInvoice(BElectronic fp) throws ElectronicException {
		int n = first(fp);
		if (-1 == n) {
			return fp;
		}
		BigDecimal paysum = BigDecimal.ZERO;
		BElectronic yfp = mapper.getInvoiceByFPH(fp.getInvoicenum(), fp.getInvoiceversion(), "正票",
				fp.getInvoicemethod());
		if (yfp == null)
			return error(fp, "未获取到发票");
		yfp.setFlag("2");
		mapper.update(yfp);
		fp.setActs(mapper.getAccount(yfp.getAccountids()));
		fp.setAccountids("-1");
		fp.setHouseid(yfp.getHouseid());
		fp.setTel(yfp.getTel());
		fp.setMoney(BigDecimal.ZERO.subtract(yfp.getMoney()));
		fp.setCardno(yfp.getCardno());
		fp.setEmail(yfp.getEmail());
		fp.setGfmc(yfp.getGfmc());
		fp.setNsrsbh(yfp.getNsrsbh());
		fp.setKhh(yfp.getKhh());
		fp.setDz(yfp.getDz());
		fp.setInvoicemethod(yfp.getInvoicemethod());
		fp.setInvoicekind("负票");
		fp.setReverselsh(yfp.getLsh());
		fp.setReturncode("0000");
		fp.setReturnstate(null);
		fp.setFlag("1");
		JSONObject order = new JSONObject();
		order.put("buyerName", Tools.toString(fp.getGfmc()));
		order.put("buyerTaxNum", Tools.toString(fp.getNsrsbh()));
		order.put("buyerTel", Tools.toString(fp.getTel()));
		order.put("buyerAddress", Tools.toString(fp.getDz()));
		order.put("buyerAccount", Tools.toString(fp.getKhh()));
		order.put("salerTaxNum", Tools.toString(ele.nsrsbh));
		order.put("salerTel", Tools.toString(ele.nsrdh));
		order.put("salerAddress", Tools.toString(ele.nsrdz));
		order.put("salerAccount", Tools.toString(ele.yhzh));
		order.put("orderNo", Tools.getUUID());
		order.put("invoiceDate", Tools.toString(Tools.DATEFORMAT_Y_M_D_HMS.format(new Date())));
		order.put("remark", Tools.toString(fp.getRemark()));
		order.put("checker", Tools.toString(fp.getFhr()));
		order.put("payee", Tools.toString(fp.getSkr()));
		order.put("clerk", Tools.toString(fp.getKpr()));
		order.put("invoiceCode", Tools.left(fp.getInvoiceversion(), 12, "0"));
		order.put("invoiceNum", Tools.left(fp.getInvoicenum(), 8, "0"));
		order.put("pushMode", Tools.toString(!Tools.isNullOrEmpty(fp.getTel()) && !Tools.isNullOrEmpty(fp.getEmail())
				? "2" : !Tools.isNullOrEmpty(fp.getTel()) ? "1" : !Tools.isNullOrEmpty(fp.getEmail()) ? "0" : "-1"));
		order.put("buyerPhone", Tools.toString(fp.getTel()));
		order.put("email", Tools.toString(fp.getEmail()));
		order.put("invoiceType", "2");
		order.put("invoiceLine", "c");
		order.put("extensionNumber", users[n][1]);
		order.put("terminalNumber", users[n][2]);
		JSONArray array = new JSONArray();
		for (Account mp : fp.getActs()) {
			JSONObject dtl = new JSONObject();
			Taxrate taxrate = tax.get(mp.getAreakind());
			if (0 == BigDecimal.ZERO.compareTo(mp.getArea())) {
				mp.setArea(BigDecimal.ONE);
			}
			if ("5".equals(mp.getActflag1())) {
				mp.setAreaname(Tools.toString(taxrate.getAreaname()).concat("-违约金"));
			}
			dtl.put("goodsName", mp.getAreaname());
			dtl.put("goodsCode", "11001020101");
			dtl.put("withTaxFlag", taxrate.getIsdutyfree());
			dtl.put("specType", Tools.toString(mp.getAnnual()));
			dtl.put("unit", "平方米");
			if ("1".equals(taxrate.getIsdutyfree())) {
				mp.setReceivedsum(
						mp.getReceived().divide(BigDecimal.ONE.add(taxrate.getTaxrate()), 8, BigDecimal.ROUND_HALF_UP));
				mp.setSe(mp.getReceived().subtract(mp.getReceivedsum()));
			} else {
				mp.setReceivedsum(mp.getReceived());
				mp.setSe(BigDecimal.ZERO);
			}
			dtl.put("tax", "-".concat(Tools.toString(mp.getSe())));
			dtl.put("taxRate", isdutyfree(mp) ? "0" : Tools.toString(taxrate.getTaxrate()));
			dtl.put("num", "-".concat(Tools.toString(mp.getArea())));
			dtl.put("price", Tools.toString(mp.getReceived().divide(mp.getArea(), 8, BigDecimal.ROUND_HALF_UP)));
			dtl.put("taxExcludedAmount", "-".concat(Tools.toString(mp.getReceivedsum())));
			dtl.put("taxIncludedAmount", "-".concat(Tools.toString(mp.getReceived())));
			dtl.put("favouredPolicyName", isdutyfree(mp) ? "免税" : "");
			dtl.put("favouredPolicyFlag", isdutyfree(mp) ? "1" : "");
			dtl.put("zeroRateFlag", isdutyfree(mp) ? "1" : "");
			array.add(dtl);
			paysum = paysum.add(mp.getReceived());
		}
		order.put("invoiceDetail", Tools.toString(array));
		JSONObject content = new JSONObject();
		content.put("order", order);
		log.info("红冲请求报文:" + content.toString());
		JSONObject web = web(ele.url, kp, content.toString());
		log.info(web.toString());
		if (web != null && SUCCESS.equals(web.getString("code"))) {
			fp.setReturncode("0000");
			fp.setLsh(web.getJSONObject("result").getString("invoiceSerialNum"));
		} else {
			fp.setReturncode("9999");
			fp.setReturnstate(web.getString("describe"));
		}

		if (!"0000".equals(fp.getReturncode()))
			return fp;

		// 查询开票结果
		StringBuilder search = new StringBuilder();
		search.append("{\"isOfferInvoiceDetail\": \"\", \"orderNos\": [], \"serialNos\": [");
		search.append("\"").append(fp.getLsh()).append("\"");
		search.append("]}");
		for (int num = 0; num < 5; num++) {
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			web = web(ele.url, cx, search.toString());
			log.info("查询结果:" + web.toString());
			if (web != null && SUCCESS.equals(web.getString("code"))) {
				array = web.getJSONArray("result");
				web = JSONObject.fromObject(array.get(0));
				if ("20".equals(web.getString("status")) || "21".equals(web.getString("status"))) {
					continue;
				}
				if ("2".equals(web.getString("status"))) {
					fp.setReturncode("0000");
					fp.setReturnstate(web.getString("statusMsg"));
					fp.setPdfpath(web.getString("pdfUrl"));
					fp.setInvoicenum(web.getString("invoiceNo"));
					fp.setInvoiceversion(web.getString("invoiceCode"));
				} else {
					fp.setReturncode("9999");
					fp.setReturnstate(web.getString("failCause"));
				}
				break;
			}
		}
		// 客户端在线状态检测
		/*
		 * StringBuilder test = new StringBuilder();
		 * test.append("{\"sellerTaxNo\": \"").append(ele.nsrsbh).
		 * append("\",\"extensionNumber\": \"0\"}"); web = web(ele.url, lj,
		 * test.toString()); if (web != null &&
		 * SUCCESS.equals(web.getString("code"))) { if
		 * (!"1".equals(web.getJSONObject("result").getString("onlineStatus")))
		 * { fp.setReturncode("9999"); fp.setReturnstate("打印机不在线"); } }
		 */

		// 密文
		if ("0000".equals(fp.getReturncode())) {
			try {
				fp.setPdfbytes(jiami(fp.getInvoicenum(), fp.getInvoiceversion(), paysum));
			} catch (Exception e) {
			}
		}

		mapper.insert(fp);
		mapper.clearInvoiceById(yfp.getAccountids());
		yfp.setFlag("1");
		mapper.update(yfp);
		return fp;
	}

	@Override
	public BElectronic zfInvoice(BElectronic fp) throws ElectronicException {
		fp = mapper.getInvoiceByFPH(fp.getInvoicenum(), fp.getInvoiceversion(), "正票", fp.getInvoicemethod());
		if (fp == null) {
			return error(fp, "未获取到发票");
		}
		JSONObject web = new JSONObject();
		web.put("invoiceId", fp.getLsh());
		web.put("invoiceCode", fp.getInvoiceversion());
		web.put("invoiceNo", fp.getInvoicenum());
		web = web(ele.url, hc, web.toString());
		if (web != null && SUCCESS.equals(web.getString("code"))) {
			fp.setReturncode("0000");
			fp.setReturnstate("提交成功");
		} else {
			fp.setReturncode("9999");
			fp.setReturnstate("提交失败");
		}
		return fp;
	}

	@Override
	public void searchInvoice() {

	}

	@Override
	public void kp() {

	}

	public BElectronic reSend(BElectronic be) {
		String content = "{" + "\"mail\": \"" + Tools.toString(be.getEmail()) + "\"," + "\"phone\": \""
				+ Tools.toString(be.getTel()) + "\"," + "\"taxnum\": \"" + Tools.toString(ele.nsrsbh) + "\","
				+ "\"invoiceCode\": \"" + Tools.toString(be.getInvoiceversion()) + "\"," + "\"invoiceNum\": \""
				+ Tools.toString(be.getInvoicenum()) + "\"" + "}";
		JSONObject web = web(ele.url, ck, content);
		if (web != null && SUCCESS.equals(web.getString("code"))) {
			be.setReturncode("0000");
			be.setLsh(web.getJSONObject("result").getString("invoiceSerialNum"));
		} else {
			be.setReturncode("9999");
			be.setReturnstate(web.getString("describe"));
		}
		return be;
	}

	@Override
	public BElectronic sendInvoice(BElectronic be) throws ElectronicException {
		return null;
	}

	public JSONObject web(String url, String method, String content) {
		JSONObject js = null;
		NNOpenSDK sdk = NNOpenSDK.getIntance();
		String str = sdk.sendPostSyncRequest(url, Tools.getUUID(), appKey, appSecret, token, ele.nsrsbh, method,
				sdk.convertToUtf8(content));
		if (str != null && !"".equals(str))
			js = JSONObject.fromObject(str);
		return js;
	}

	/**
	 * @刷新身份令牌
	 */
	public void token() {
//		 int i = 0;
//		 do {
//		 try {
//		 String str = NNOpenSDK.getIntance().getMerchantToken(appKey,
//		 appSecret);
//		 if (str != null) {
//		 JSONObject js = JSONObject.fromObject(str);
//		 if (js.has("access_token")) {
//		 token = js.getString("access_token");
//		 return;
//		 }
//		 }
//		 } catch (Exception e) {
//		 }
//		 i++;
//		 } while (i < 3);
		log.info("token获取异常");
	}

	public String jiami(String fph, String bbh, BigDecimal money) {
		String str = null;
		try {
			String ss = "01!" + bbh + "!" + fph + "!" + money.toPlainString();
			String aes = AesUtilTest.aesEncryptC(ss, "9wqj9jHQoqwM0ESN");
			String pub = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClj0t1b+O5Cq06d0yp4qZHM3OhNSmoaArC6qAhehT/DB23F/CCUSFrQCjADhOvCq+xu4JcNGQ1kpjhKVNb642QPlSDJ04QM/+3mKcu/WKLDZ+3zQYvNY41pcjTyxtUT9ixaBx8OQQfOp+qiAYYBtE9T6WRLCrl1YN0drpDvFylyQIDAQAB";
			String rsa = RSADemo.encrypt(aes, RSADemo.getPublickey(pub));
			str = URLEncoder.encode(ele.nsrsbh + "!" + rsa + "!01", "UTF-8");
		} catch (Exception e) {
			log.info(Tools.getErrorException(e));
		}
		return str;
	}

}
